package com.itheima.d3_charset;

import java.util.Arrays;

/**
 * 目标：掌握如何使用Java代码完成对字符的编码和解码。
 *
 * 标准ASCII字符集
 * ASCII(American Standard Code for Information Interchange)： 美国信息交换标准代码，包括了英文、符号等。
 *  标准ASCII使用1个字节存储一个字符，首尾是0，剩下七位是可以用来编码，总共可表示128个字符，对美国佬来说完全够用。
 *
 *  GBK（汉字内码扩展规范，国标）
 * 汉字编码字符集，包含了2万多个汉字等字符，GBK中一个中文字符编码成两个字节的形式存储。
 * 注意：GBK兼容了ASCII字符集。
 * GBK规定：汉字的第一个字节的第一位必须是1
 *
 * Unicode字符集(统一码，也叫万国码)
 * Unicode是国际组织制定的，可以容纳世界上所有文字、符号的字符集。
 *
 * utf-8
 * 是Unicode字符集的一种编码方案，采取可变长编码方案，共分四个长度区：1个字节，2个字节，3个字节，4个字节
 * 英文字符、数字等只占1个字节（兼容标准ASCII编码），汉字字符占用3个字节。
 * a      97        01100001
 * 我     25105     110 001000 010001
 * m      109       01101101
 *01100001  1110xxxx 10xxxxxxx 10xxxxxx 01101101
 *
 * UTF-8编码方式(二进制)
 * 0xxxxxxx  （ASCII码）
 * 110xxxxx  10xxxxxx
 * 1110xxxx  10xxxxxx  10xxxxxx
 * 11110xxx  10xxxxxx  10xxxxxx  10xxxxxx
 *
 * 注意：技术人员在开发时都应该使用UTF-8编码!
 *
 * ASCII字符集：只有英文、数字、符号等，占1个字节。
 * GBK字符集：汉字占2个字节，英文、数字占1个字节。
 * UTF-8字符集：汉字占3个字节，英文、数字占1个字节。
 *
 * 注意1：字符编码时使用的字符集，和解码时使用的字符集必须一致，否则会出现乱码
 * 注意2：英文，数字一般不会乱码，因为很多字符集都兼容了ASCII编码。
 *
 *  编码：把字符按照指定字符集编码成字节
 *  解码：把字节按照指定字符集解码成字符
 *
 *  在将来的开发中，在通信或者数字加密会设计到相关运用
 */
public class Test {
    public static void main(String[] args) throws Exception {
        // 1、Java代码完成对字符的编码，String提供了如下方法
        // byte[] getBytes()   使用平台的默认字符集将该 String编码为一系列字节，将结果存储到新的字节数组中
        // byte[] getBytes(String charsetName)       使用指定的字符集将该 String编码为一系列字节，将结果存储到新的字节数组中

        String data = "a我b";    //utf-8中a和b占一个字节，汉字我占三个字节：[97, -26, -120, -111, 98]
        byte[] bytes = data.getBytes(); // 默认是按照平台字符集（UTF-8）进行编码的。
        System.out.println("getBytes编码后的字符数组bytes内容： "+Arrays.toString(bytes));

        // 按照指定字符集进行编码。
        //GBK中a与b各占一个字节，汉字我占两个字节：[97, -50, -46, 98]
        byte[] bytes1 = data.getBytes("GBK");   //例如字符集写成GKB，抛异常：Unhandled exception: java.io.UnsupportedEncodingException
        System.out.println("getBytes按照指定字符集GBK编码后的字符数组bytes1内容： "+Arrays.toString(bytes1));

        // 2、Java代码完成对字符的解码，String提供了如下方法
        //  String(byte[] bytes)       通过使用平台的默认字符集解码指定的字节数组来构造新的 String
        //  String(byte[] bytes, String charsetName)    通过指定的字符集解码指定的字节数组来构造新的 String
        String s1 = new String(bytes); // 按照平台默认编码（UTF-8）解码
        System.out.println("上面按照默认utf-8编码的字符数组bytes，按照默认utf-8解码转字符串的结果： "+s1);

        //输出结果是a��b，乱码，因为GBK编码的汉字我占两个字节，这两个字节按照UTF-8解码不认识，就输出两个问号
        String s2 = new String(bytes1);
        System.out.println("上面按照GBK编码的bytes1，按照默认UTF-8解码的结果： "+s2);

        String s3 = new String(bytes1, "GBK");
        System.out.println("上面按照GBK编码的bytes1，按照指定GBK解码的结果： "+s3);


        System.out.println("-----------------------自己试一试----------------");

        String zeng1 = new String("我很帅滴la");
        System.out.println(zeng1);
        byte[] zeng1Bytes = zeng1.getBytes("GBK");
        System.out.println(zeng1Bytes);
        System.out.println(Arrays.toString(zeng1Bytes));

        String zeng1String = new String(zeng1Bytes, "UTF-8");
        System.out.println(zeng1String);

        String zeng1String2 = new String(zeng1Bytes,"GBK");
        System.out.println(zeng1String2);
    }
}

